<?php


namespace sws;


class Event
{
    /**
     * 监听者
     * @var array
     */
    protected $listener = [];

    /**
     * 获取实例
     * @return Event
     */
    public static function getInstance(): Event
    {
        return Container::getInstance()->make(Event::class);
    }

    /**
     * 注册监听事件
     * @param string $event
     * @param $listener
     * @param bool $priority
     * @return $this
     */
    public function listen(string $event, $listener, bool $priority = false): Event
    {
        if ($priority && isset($this->listener[$event])) {
            array_unshift($this->listener[$event], $listener);
        } else {
            $this->listener[$event][] = $listener;
        }
        return $this;
    }

    /**
     * 触发事件
     * @param $event
     * @param array $params
     * @param bool $trace 是否追踪事件（事件返回false,后续事件不再执行）
     * @return array|mixed
     */
    public function trigger($event, array $params = [], bool $trace = true)
    {
        $result = [];
        if (is_string($event)) {
            $listeners = $this->listener[$event] ?? [];
            $listeners = array_unique($listeners, SORT_REGULAR);

            foreach ($listeners as $key => $listener) {
                $result[$key] = Container::getInstance()->invoke($listener, $params);
                if (true === $trace && false === $result[$key]) {
                    break;
                }
            }
        } else {
            $result[] = Container::getInstance()->invoke($event, $params);
        }
        return $trace ? end($result) : $result;
    }

    /** 是否存在事件监听
     * @param string $event
     * @return bool
     */
    public function hasListener(string $event): bool
    {
        return isset($this->listener[$event]);
    }

    /**
     * 获取事件监听列表
     * @param string $event
     * @return array|mixed
     */
    public function getListens(string $event)
    {
        if (true === $this->hasListener($event)) {
            return $this->listener[$event];
        }
        return [];
    }

    /**
     * 删除事件监听
     * @param string $event
     * @param array|null $listener 必须是设置监听的数组格式[class,method]
     * @return $this
     */
    public function removeListener(string $event, array $listener = null): Event
    {
        if (null === $listener) {
            unset($this->listener[$event]);
        } else {
            if (isset($this->listener[$event])) {
                foreach ($this->listener[$event] as $k => $item) {
                    if ($listener == $item) {
                        unset($this->listener[$event][$k]);
                    }
                }
            }
        }
        return $this;
    }


}